﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using System.IO;
using System.Xml;
using Microsoft.Xna.Framework;

namespace Fishes.Objects
{
    public class Toolbar
    {
        #region Properties

        public int NumberOfSlots
        {
            get { return _numberOfSlots; }
        }
        private int _numberOfSlots = 0;

        public Vector2 SlotSize
        {
            get { return _slotSize; }
        }
        private Vector2 _slotSize = Vector2.Zero;

        public Vector2 StatsSize
        {
            get { return _statsSize; }
        }
        private Vector2 _statsSize = Vector2.Zero;

        public Vector2 Size
        {
            get
            {
                return new Vector2(this.StatsSize.X,
                    this.StatsSize.Y + this.SlotSize.Y);
            }
        }

        public Texture2D SlotImage
        {
            get { return _slotImage; }
        }
        private Texture2D _slotImage = null;

        public Texture2D StatsBackground
        {
            get { return _statsBackground; }
        }
        private Texture2D _statsBackground = null;

        public List<Tool> Tools
        {
            get { return _tools; }
        }
        private List<Tool> _tools = new List<Tool>();

        public Tool SelectedTool
        {
            get { return _selectedTool; }
            set { _selectedTool = value; }
        }
        private Tool _selectedTool = null;

        #endregion

        #region Public Methods

        public bool Load(string path, GraphicsDevice g)
        {
            try
            {
                FileStream fp = File.Open(path, FileMode.Open);

                XmlDocument doc = new XmlDocument();
                doc.Load(fp);

                this._numberOfSlots = Convert.ToInt32(doc.SelectSingleNode("toolbar/numberOfSlots").InnerText);

                int w = Convert.ToInt32(doc.SelectSingleNode("toolbar/slotWidth").InnerText);
                int h = Convert.ToInt32(doc.SelectSingleNode("toolbar/slotHeight").InnerText);
                this._slotSize = new Vector2(w, h);

                // we can only have a max number of slots, compute that
                int maxSlots = (int)(Game1.Tank.Size.X / w);
                this._numberOfSlots = this._numberOfSlots > maxSlots ? maxSlots : this._numberOfSlots;

                if (this.SlotImage != null)
                {
                    this._slotImage.Dispose();
                    this._slotImage = null;
                }

                string slotImageFileName = doc.SelectSingleNode("toolbar/slotImage").InnerText;
                this._slotImage = Texture2D.FromFile(g, slotImageFileName, w, h);

                this._statsSize.X = Game1.Tank.Size.X;
                this._statsSize.Y = Convert.ToInt32(doc.SelectSingleNode("toolbar/statsHeight").InnerText);

                if (this.StatsBackground != null)
                {
                    this._statsBackground.Dispose();
                    this._statsBackground = null;
                }

                string statsBackgroundFileName = doc.SelectSingleNode("toolbar/statsBackground").InnerText;
                this._statsBackground = Texture2D.FromFile(g, statsBackgroundFileName,
                    (int)Game1.Tank.Size.X, (int)this.StatsSize.Y);

                fp.Close();
                fp.Dispose();

                if (!this.LoadTools(g))
                    throw new InvalidOperationException("Failed to load tools.");
            }
            catch (Exception ex)
            {
                return false;
            }

            return true;
        }

        public bool Destroy()
        {
            foreach (Tool tool in this.Tools)
                tool.Destroy();

            this.Tools.Clear();

            this.SlotImage.Dispose();
            this._slotImage = null;

            this.StatsBackground.Dispose();
            this._statsBackground = null;

            return true;
        }

        public void Render(SpriteBatch sb)
        {
            this.RenderTools(sb);
            this.RenderStats(sb);
        }

        public void OnMouseClick(Vector2 pos)
        {
            if(this.SelectedTool == null)
            {
                foreach (Tool tool in this.Tools)
                {
                    if (pos.X >= tool.Position.X &&
                        pos.X <= tool.Position.X + tool.Size.X &&
                        pos.Y >= tool.Position.Y &&
                        pos.Y <= tool.Position.Y + tool.Size.Y)
                    {
                        tool.IsSelected = true;
                        this.SelectedTool = tool;
                        break;
                    }
                }
            }
        }

        public void OnMouseUp(Game1 engine)
        {
            if (SelectedTool == null)
                return;

            this.SelectedTool.IsSelected = false;
            this.SelectedTool.OnMouseUp(engine);
            this.SelectedTool = null;
        }

        #endregion

        #region Private Methods

        private void RenderStats(SpriteBatch sb)
        {
            Rectangle dest = new Rectangle();

            dest.X = 0;
            dest.Y = (int)Game1.Tank.Size.Y + (int)this.SlotSize.Y;
            dest.Width = (int)this.StatsSize.X;
            dest.Height = (int)this.StatsSize.Y;

            sb.Draw(this.StatsBackground, dest, Color.White);

            if (Game1.Tank.SelectedFish != null)
            {
                Fish fish = Game1.Tank.SelectedFish;

                Vector2 pos = new Vector2(0, dest.Y);

                sb.DrawString(Game1.GameFont,
                    String.Format("Name: {0}", fish.Name),
                    pos,
                    Color.Black);

                if (fish.AiState == Fish.FishAIState.Dead)
                {
                    pos.Y += Game1.GameFont.LineSpacing;
                    sb.DrawString(Game1.GameFont,
                        "Dead",
                        pos,
                        Color.Black);
                }
                else
                {
                    pos.Y += Game1.GameFont.LineSpacing;
                    sb.DrawString(Game1.GameFont,
                        String.Format("Hunger: {0}/{1}", fish.Hunger.CurrentValue, fish.Hunger.Value),
                        pos,
                        Color.Black);
                }
            }
        }

        private void RenderTools(SpriteBatch sb)
        {
            Rectangle dest = new Rectangle();

            for (int i = 0; i < this._numberOfSlots; i++)
            {
                dest.X = i * (int)this.SlotSize.X;
                dest.Y = (int)Game1.Tank.Size.Y;
                dest.Width = (int)this.SlotSize.X;
                dest.Height = (int)this.SlotSize.Y;

                sb.Draw(this.SlotImage, dest, Color.White);

                // render at the same time to save some cycles...
                if (i < this.Tools.Count)
                {
                    this.Tools[i].Position = new Vector2(dest.X, dest.Y);
                    this.Tools[i].Render(sb);
                }
            }
        }

        private bool LoadTools(GraphicsDevice g)
        {
            try
            {
                string[] paths = Directory.GetFiles("toolbar\\", "*.tool");

                foreach (string path in paths)
                {
                    Tool tool = new Tool();
                    if (!tool.Load(path, g, this.SlotSize))
                        throw new InvalidOperationException(String.Format("Failed to load tool: {0}",
                            path));

                    this.Tools.Add(tool);
                }
            }
            catch (Exception ex)
            {
                return false;
            }

            return true;
        }

        #endregion
    }
}
